home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 24 / CU Amiga Magazine's Super CD-ROM 24 (1998)(EMAP Images)(GB)(Track 1 of 2)[!][issue 1998-07].iso / CUCD / Programming / SWI / source / src / pl-arith.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-15  |  29.3 KB  |  1,373 lines

  1. /*  $Id: pl-arith.c,v 1.36 1998/04/15 15:16:52 jan Exp $
  2.  
  3.     Copyright (c) 1990 Jan Wielemaker. All rights reserved.
  4.     See ../LICENCE to find out about your rights.
  5.     jan@swi.psy.uva.nl
  6.  
  7.     Purpose: arithmetic built in functions
  8. */
  9.  
  10. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  11. The arithmetic module defines a small set of logical integer  predicates
  12. as   well   as  the  evaluation  of  arbitrary  arithmetic  expressions.
  13. Arithmetic can be interpreted or compiled (see  -O  flag).   Interpreted
  14. arithmetic  is  supported  by  the  built-in  predicates is/2, >/2, etc.
  15. These functions call valueExpression() to evaluate a Prolog term holding
  16. an arithmetic expression.
  17.  
  18. For compiled arithmetic, the compiler generates WAM codes that execute a
  19. stack machine.  This module maintains an array of arithmetic  functions.
  20. These  functions are addressed by the WAM instructions using their index
  21. in this array.
  22.  
  23. The  current  version  of  this  module  also  supports  Prolog  defined
  24. arithmetic  functions.   In  the  current  version these can only return
  25. numbers.  This should be changed to return arbitrary Prolog  terms  some
  26. day.
  27. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  28.  
  29. #include <math.h>            /* avoid abs() problem with MSVC++ */
  30. #include "pl-incl.h"
  31. #ifndef M_PI
  32. #define M_PI (3.14159265358979323846)
  33. #endif
  34. #ifndef M_E
  35. #define M_E (2.7182818284590452354)
  36. #endif
  37.  
  38. #if !defined(HAVE_ISNAN) && defined(NaN)
  39. #define isnan(f)  ((f) == NaN)
  40. #define HAVE_ISNAN
  41. #endif
  42.  
  43. #ifdef HAVE___TRY
  44. #include <excpt.h>
  45. #endif
  46.  
  47. typedef int (*ArithF)();
  48.  
  49. struct arithFunction
  50. { ArithFunction next;        /* Next of chain */
  51.   functor_t    functor;    /* Functor defined */
  52.   ArithF    function;    /* Implementing function */
  53.   Module    module;        /* Module visibility module */
  54. #if O_PROLOG_FUNCTIONS
  55.   Procedure    proc;        /* Prolog defined functions */
  56. #endif
  57. #if O_COMPILE_ARITH
  58.   code        index;        /* Index of function */
  59. #endif
  60. };
  61.  
  62. #define arithFunctionTable    (GD->arith.table)
  63. #define function_array        (&GD->arith.functions)
  64. #define FunctionFromIndex(n)    fetchBuffer(function_array, n, ArithFunction)
  65.  
  66. static ArithFunction    isCurrentArithFunction(functor_t, Module);
  67. static void        registerFunction(ArithFunction f);
  68. static void        promoteToRealNumber(Number n);
  69.  
  70.  
  71.         /********************************
  72.         *   LOGICAL INTEGER FUNCTIONS   *
  73.         *********************************/
  74.  
  75. word
  76. pl_between(term_t low, term_t high, term_t n, word b)
  77. { switch( ForeignControl(b) )
  78.   { case FRG_FIRST_CALL:
  79.       { long l, h, i;
  80.  
  81.     if ( !PL_get_long(low, &l) )
  82.       return PL_error("between", 3, NULL, ERR_TYPE, ATOM_integer, low);
  83.     if ( !PL_get_long(high, &h) )
  84.       return PL_error("between", 3, NULL, ERR_TYPE, ATOM_integer, high);
  85.  
  86.     if ( PL_get_long(n, &i) )
  87.     { if ( i >= l && i <= h )
  88.         succeed;
  89.       fail;
  90.     }
  91.     if ( !PL_is_variable(n) )
  92.       return PL_error("between", 3, NULL, ERR_TYPE, ATOM_integer, n);
  93.     if ( h < l )
  94.       fail;
  95.  
  96.     PL_unify_integer(n, l);
  97.     if ( l == h )
  98.       succeed;
  99.     ForeignRedoInt(l);
  100.       }
  101.     case FRG_REDO:
  102.       { long next = ForeignContextInt(b) + 1;
  103.     long h;
  104.  
  105.     PL_unify_integer(n, next);
  106.     PL_get_long(high, &h);
  107.     if ( next == h )
  108.       succeed;
  109.     ForeignRedoInt(next);
  110.       }
  111.     default:;
  112.       succeed;
  113.   }
  114. }
  115.  
  116. word
  117. pl_succ(term_t n1, term_t n2)
  118. { long i1, i2;
  119.  
  120.   if ( PL_get_long(n1, &i1) )
  121.   { if ( PL_get_long(n2, &i2) )
  122.       return i1+1 == i2 ? TRUE : FALSE;
  123.     else if ( PL_unify_integer(n2, i1+1) )
  124.       succeed;
  125.  
  126.     return PL_error("succ", 2, NULL, ERR_TYPE, ATOM_integer, n2);
  127.   }
  128.   if ( PL_get_long(n2, &i2) )
  129.   { if ( PL_unify_integer(n1, i2-1) )
  130.       succeed;
  131.   }
  132.  
  133.   return PL_error("succ", 2, NULL, ERR_TYPE, ATOM_integer, n1);
  134. }
  135.  
  136.  
  137. static int
  138. var_or_long(term_t t, long *l, int which, int *mask)
  139. { if ( PL_get_long(t, l) )
  140.   { *mask |= which;
  141.     succeed;
  142.   } 
  143.   if ( PL_is_variable(t) )
  144.     succeed;
  145.     
  146.   return PL_error("plus", 3, NULL, ERR_TYPE, ATOM_integer, t);
  147. }
  148.  
  149.  
  150. word
  151. pl_plus(term_t a, term_t b, term_t c)
  152. { long m, n, o;
  153.   int mask = 0;
  154.  
  155.   if ( !var_or_long(a, &m, 0x1, &mask) ||
  156.        !var_or_long(b, &n, 0x2, &mask) ||
  157.        !var_or_long(c, &o, 0x4, &mask) )
  158.     fail;
  159.  
  160.   switch(mask)
  161.   { case 0x7:
  162.       return m+n == o ? TRUE : FALSE;
  163.     case 0x3:                /* +, +, - */
  164.       return PL_unify_integer(c, m+n);
  165.     case 0x5:                /* +, -, + */
  166.       return PL_unify_integer(b, o-m);
  167.     case 0x6:                /* -, +, + */
  168.       return PL_unify_integer(a, o-n);
  169.     default:
  170.       return PL_error("succ", 2, NULL, ERR_INSTANTIATION);
  171.   }
  172. }
  173.  
  174.  
  175.         /********************************
  176.         *           COMPARISON          *
  177.         *********************************/
  178.  
  179. int
  180. ar_compare(Number n1, Number n2, int what)
  181. { int result;
  182.  
  183.   if ( intNumber(n1) && intNumber(n2) )
  184.   { switch(what)
  185.     { case LT:    result = n1->value.i <  n2->value.i; break;
  186.       case GT:  result = n1->value.i >  n2->value.i; break;
  187.       case LE:    result = n1->value.i <= n2->value.i; break;
  188.       case GE:    result = n1->value.i >= n2->value.i; break;
  189.       case NE:    result = n1->value.i != n2->value.i; break;
  190.       case EQ:    result = n1->value.i == n2->value.i; break;
  191.       default:    fail;
  192.     }
  193.     if ( result )
  194.       succeed;
  195.   } else
  196.   { promoteToRealNumber(n1);
  197.     promoteToRealNumber(n2);
  198.  
  199.     switch(what)
  200.     { case LT:    result = n1->value.f <  n2->value.f; break;
  201.       case GT:  result = n1->value.f >  n2->value.f; break;
  202.       case LE:    result = n1->value.f <= n2->value.f; break;
  203.       case GE:    result = n1->value.f >= n2->value.f; break;
  204.       case NE:    result = n1->value.f != n2->value.f; break;
  205.       case EQ:    result = n1->value.f == n2->value.f; break;
  206.       default:    fail;
  207.     }
  208.     if ( result )
  209.       succeed;
  210.   }  
  211.  
  212.   fail;
  213. }
  214.  
  215.  
  216. static word
  217. compareNumbers(term_t n1, term_t n2, int what)
  218. { number left, right;
  219.  
  220.   TRY(valueExpression(n1, &left) &&
  221.       valueExpression(n2, &right));
  222.  
  223.   return ar_compare(&left, &right, what);
  224. }
  225.  
  226.  
  227. word
  228. pl_lessNumbers(term_t n1, term_t n2)            /* </2 */
  229. { return compareNumbers(n1, n2, LT);
  230. }
  231.  
  232. word
  233. pl_greaterNumbers(term_t n1, term_t n2)            /* >/2 */
  234. { return compareNumbers(n1, n2, GT);
  235. }
  236.  
  237. word
  238. pl_lessEqualNumbers(term_t n1, term_t n2)        /* =</2 */
  239. { return compareNumbers(n1, n2, LE);
  240. }
  241.  
  242. word
  243. pl_greaterEqualNumbers(term_t n1, term_t n2)        /* >=/2 */
  244. { return compareNumbers(n1, n2, GE);
  245. }
  246.  
  247. word
  248. pl_nonEqualNumbers(term_t n1, term_t n2)        /* =\=/2 */
  249. { return compareNumbers(n1, n2, NE);
  250. }
  251.  
  252. word
  253. pl_equalNumbers(term_t n1, term_t n2)            /* =:=/2 */
  254. { return compareNumbers(n1, n2, EQ);
  255. }
  256.  
  257.         /********************************
  258.         *           FUNCTIONS           *
  259.         *********************************/
  260.  
  261. static ArithFunction
  262. isCurrentArithFunction(functor_t f, Module m)
  263. { ArithFunction a;
  264.   ArithFunction r = NULL;
  265.   int level = 30000;
  266.  
  267.   for(a = arithFunctionTable[functorHashValue(f, ARITHHASHSIZE)];
  268.       a && !isTableRef(a); a = a->next)
  269.   { if ( a->functor == f )
  270.     { Module m2;
  271.       int l;
  272.  
  273.       for( m2 = m, l = 0; m2; m2 = m2->super, l++ )
  274.       { if ( m2 == a->module && l < level )
  275.     { r = a;
  276.       level = l;
  277.     }
  278.       }
  279.     }
  280.   }
  281.  
  282.   return r;
  283. }
  284.  
  285. #if HAVE_SIGNAL
  286. typedef void (*OsSigHandler)(int);
  287.  
  288. static void
  289. realExceptionHandler(int sig, int type, SignalContext scp, char *addr)
  290. {
  291. #ifndef BSD_SIGNALS
  292.   signal(sig, (OsSigHandler)realExceptionHandler);
  293. #endif
  294.   if ( LD->in_arithmetic > 0 )
  295.   { warning("Floating point exception");
  296. #ifndef O_RUNTIME
  297.     Sfprintf(Serror, "[PROLOG STACK:\n");
  298.     backTrace(NULL, 10);
  299.     Sfprintf(Serror, "]\n");
  300. #endif
  301.     pl_abort();
  302.   } else
  303.   { deliverSignal(sig, type, scp, addr);
  304.   }
  305. }
  306. #endif
  307.  
  308. #if __TURBOC__
  309. static int
  310. realExceptionHandler(e)
  311. struct exception *e;
  312. { warning("Floating point exception");
  313.  
  314.   pl_abort();
  315.   /*NOTREACHED*/
  316.   fail;                /* make tc happy */
  317. }
  318. #endif
  319.  
  320.  
  321. #if O_PROLOG_FUNCTIONS
  322.  
  323. static int prologFunction(ArithFunction, term_t, Number);
  324.  
  325. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  326. Activating a Prolog predicate as function below the arithmetic functions
  327. is/0, >, etc. `f' is the arithmetic function   to  be called. `t' is the
  328. base term-reference of an array holding  the proper number of arguments.
  329. `r' is the result of the evaluation.
  330.  
  331. This calling convention is somewhat  unnatural,   but  fits  best in the
  332. calling convention required by ar_func_n() below.
  333. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  334.  
  335. static int
  336. prologFunction(ArithFunction f, term_t av, Number r)
  337. { int arity = f->proc->definition->functor->arity;
  338.   fid_t fid = PL_open_foreign_frame();
  339.   qid_t qid;
  340.   int rval;
  341.  
  342.   qid = PL_open_query(NULL, PL_Q_CATCH_EXCEPTION, f->proc, av);
  343.  
  344.   if ( PL_next_solution(qid) )
  345.   { rval = valueExpression(av+arity-1, r);
  346.     PL_close_query(qid);
  347.     PL_discard_foreign_frame(fid);
  348.   } else
  349.   { term_t except;
  350.  
  351.     if ( (except = PL_exception(qid)) )
  352.     { rval = PL_throw(except);        /* pass exception */
  353.     } else
  354.     { char *name = stringAtom(f->proc->definition->functor->name);
  355.  
  356.       rval = PL_error(name, arity-1, NULL, ERR_FAILED, f->proc);
  357.     }
  358.  
  359.     PL_cut_query(qid);            /* donot destroy data */
  360.     PL_close_foreign_frame(fid);    /* same */
  361.   }
  362.  
  363.   return rval;
  364. }
  365.  
  366. #endif /* O_PROLOG_FUNCTIONS */
  367.  
  368. int
  369. valueExpression(term_t t, Number r)
  370. { ArithFunction f;
  371.   functor_t functor;
  372.   Word p = valTermRef(t);
  373.   word w;
  374.  
  375.   deRef(p);
  376.   w = *p;
  377.  
  378.   switch(tag(w))
  379.   { case TAG_INTEGER:
  380.       r->value.i = valInteger(w);
  381.       r->type = V_INTEGER;
  382.       succeed;
  383.     case TAG_FLOAT:
  384.       r->value.f = valReal(w);
  385.       r->type = V_REAL;
  386.       succeed;
  387.     case TAG_VAR:
  388.       return PL_error(NULL, 0, NULL, ERR_INSTANTIATION);
  389.     case TAG_ATOM:
  390.       functor = lookupFunctorDef(w, 0);
  391.       break;
  392.     case TAG_COMPOUND:
  393.       functor = functorTerm(w);
  394.       break;
  395.     default:
  396.       return PL_error(NULL, 0, NULL, ERR_TYPE, ATOM_number, t);
  397.   }
  398.  
  399.   if ( !(f = isCurrentArithFunction(functor,
  400.                     contextModule(environment_frame))))
  401.   { if ( functor == FUNCTOR_dot2 )    /* handle "a" (make function) */
  402.     { Word a, b, p = valTermRef(t);
  403.  
  404.       deRef(p);
  405.       a = argTermP(*p, 0);
  406.       deRef(a);
  407.       if ( isTaggedInt(*a) )
  408.       { b = argTermP(*p, 1);
  409.     deRef(b);
  410.     if ( *b == ATOM_nil )
  411.     { r->value.i = valInt(*a);
  412.       r->type = V_INTEGER;
  413.       succeed;
  414.     } else
  415.     { term_t a2 = PL_new_term_ref();
  416.       PL_get_arg(2, t, a2);
  417.       return PL_error(".", 2, NULL, ERR_TYPE, ATOM_nil, a2);
  418.     }
  419.       } else
  420.       { term_t a1 = PL_new_term_ref();
  421.     PL_get_arg(1, t, a1);
  422.     return PL_error(".", 2, NULL, ERR_TYPE, ATOM_integer, a1);
  423.       }
  424.     } else
  425.       return PL_error(NULL, 0, NULL, ERR_NOT_EVALUABLE, functor);
  426.   }
  427.  
  428. #if O_PROLOG_FUNCTIONS
  429.   if ( f->proc )
  430.   { int rval, n, arity = arityFunctor(functor);
  431.     term_t h0 = PL_new_term_refs(arity+1); /* one extra for the result */
  432.  
  433.     for(n=0; n<arity; n++)
  434.     { number n1;
  435.  
  436.       PL_get_arg(n+1, t, h0+n);
  437.       if ( valueExpression(h0+n, &n1) )
  438.       { _PL_put_number(h0+n, &n1);
  439.       } else
  440.     fail;
  441.     }
  442.  
  443.     rval = prologFunction(f, h0, r);
  444.     PL_reset_term_refs(h0);
  445.     return rval;
  446.   }
  447. #endif
  448.  
  449.   DEBUG(3, Sdprintf("Starting __try ...\n"));
  450.  
  451.   { int rval;
  452.  
  453. #ifdef HAVE___TRY
  454. #ifndef EXCEPTION_EXECUTE_HANDLER    /* lcc */
  455. #define EXCEPTION_EXECUTE_HANDLER 1
  456. #endif
  457.     __try
  458.     {
  459. #else
  460.     LD->in_arithmetic++;
  461. #endif
  462.     switch(arityFunctor(functor))
  463.     { case 0:
  464.     rval = (*f->function)(r);
  465.         break;
  466.       case 1:    
  467.       { term_t a = PL_new_term_ref();
  468.     number n1;
  469.  
  470.     PL_get_arg(1, t, a);
  471.     if ( valueExpression(a, &n1) )
  472.       rval = (*f->function)(&n1, r);
  473.     else
  474.       rval = FALSE;
  475.  
  476.     PL_reset_term_refs(a);
  477.     break;
  478.       }
  479.       case 2:
  480.       { term_t a = PL_new_term_ref();
  481.     number n1, n2;
  482.  
  483.     PL_get_arg(1, t, a);
  484.     if ( valueExpression(a, &n1) )
  485.     { PL_get_arg(2, t, a);
  486.       if ( valueExpression(a, &n2) )
  487.         rval = (*f->function)(&n1, &n2, r);
  488.       else
  489.         rval = FALSE;
  490.     } else
  491.       rval = FALSE;
  492.  
  493.     PL_reset_term_refs(a);
  494.     break;
  495.       }
  496.       default:
  497.     sysError("Illegal arity for arithmic function");
  498.         rval = FALSE;
  499.     }
  500. #if defined(HAVE___TRY)
  501.     } __except(EXCEPTION_EXECUTE_HANDLER)
  502.     { warning("Floating point exception");
  503. #ifndef O_RUNTIME
  504.       Sfprintf(Serror, "[PROLOG STACK:\n");
  505.       backTrace(NULL, 10);
  506.       Sfprintf(Serror, "]\n");
  507. #endif
  508.       pl_abort();
  509.     }
  510. #else /*HAVE___TRY*/
  511.     LD->in_arithmetic--;
  512. #endif /*HAVE___TRY*/
  513.  
  514.     if ( r->type == V_REAL )
  515.     {
  516. #ifdef HUGE_VAL
  517.       if ( r->value.f == HUGE_VAL )
  518.     return PL_error(NULL, 0, NULL, ERR_AR_OVERFLOW);
  519. #endif
  520. #ifdef HAVE_ISNAN
  521.       if ( isnan(r->value.f) )
  522.     return PL_error(NULL, 0, NULL, ERR_AR_UNDEF);
  523. #endif
  524.     }
  525.  
  526.     return rval;
  527.   }
  528. }
  529.  
  530.          /*******************************
  531.          *         CONVERSION        *
  532.          *******************************/
  533.  
  534. static void
  535. promoteToRealNumber(Number n)
  536. { if ( intNumber(n) )
  537.   { n->value.f = (real)n->value.i;
  538.     n->type = V_REAL;
  539.   }
  540. }
  541.  
  542.  
  543. int
  544. toIntegerNumber(Number n)
  545. { if ( floatNumber(n) )
  546.   { long l;
  547.  
  548. #ifdef DOUBLE_TO_LONG_CAST_RAISES_SIGFPE
  549.     if ( !((n->value.f >= PLMININT) && (n->value.f <= PLMAXINT)) )
  550.       fail;
  551. #endif
  552.  
  553.     l = (long)n->value.f;
  554.     if ( n->value.f == (real) l )
  555.     { n->value.i = l;
  556.       n->type = V_INTEGER;
  557.       succeed;
  558.     }
  559.  
  560.     fail;
  561.   }
  562.  
  563.   succeed;
  564.  
  565.  
  566. void
  567. canoniseNumber(Number n)
  568. { if ( n->type == V_REAL )        /* only if not explicit! */
  569.   { long l;
  570.  
  571. #ifdef DOUBLE_TO_LONG_CAST_RAISES_SIGFPE
  572.     if ( !((n->value.f >= PLMININT) && (n->value.f <= PLMAXINT)) )
  573.       return;
  574. #endif
  575.  
  576.     l = (long)n->value.f;
  577.     if ( n->value.f == (real) l )
  578.     { n->value.i = l;
  579.       n->type = V_INTEGER;
  580.     }
  581.   }
  582. }
  583.  
  584.  
  585.         /********************************
  586.         *     ARITHMETIC FUNCTIONS      *
  587.         *********************************/
  588.  
  589. static int
  590. ar_add(Number n1, Number n2, Number r)
  591. { if ( intNumber(n1) && intNumber(n2) ) 
  592.   { r->value.i = n1->value.i + n2->value.i; 
  593.     
  594.     if ( n1->value.i > 0 && n2->value.i > 0 && r->value.i <= 0 )
  595.       goto overflow;
  596.     if ( n1->value.i < 0 && n2->value.i < 0 && r->value.i >= 0 )
  597.       goto overflow;
  598.  
  599.     r->type = V_INTEGER;
  600.     succeed;
  601.   } 
  602.  
  603. overflow:
  604.   promoteToRealNumber(n1);
  605.   promoteToRealNumber(n2);
  606.   r->value.f = n1->value.f + n2->value.f; 
  607.   r->type = V_REAL;
  608.  
  609.   succeed;
  610. }
  611.  
  612.  
  613. static int
  614. ar_minus(Number n1, Number n2, Number r)
  615. { if ( intNumber(n1) && intNumber(n2) ) 
  616.   { r->value.i = n1->value.i - n2->value.i; 
  617.     
  618.     if ( n1->value.i > 0 && n2->value.i < 0 && r->value.i <= 0 )
  619.       goto overflow;
  620.     if ( n1->value.i < 0 && n2->value.i > 0 && r->value.i >= 0 )
  621.       goto overflow;
  622.  
  623.     r->type = V_INTEGER;
  624.     succeed;
  625.   } 
  626.  
  627. overflow:
  628.   promoteToRealNumber(n1);
  629.   promoteToRealNumber(n2);
  630.   r->value.f = n1->value.f - n2->value.f; 
  631.   r->type = V_REAL;
  632.  
  633.   succeed;
  634. }
  635.  
  636.  
  637. /* Unary functions requiring double argument */
  638.  
  639. #define UNAIRY_FLOAT_FUNCTION(name, op) \
  640.   static int \
  641.   name(Number n1, Number r) \
  642.   { promoteToRealNumber(n1); \
  643.     r->value.f = op(n1->value.f); \
  644.     r->type    = V_REAL; \
  645.     succeed; \
  646.   }
  647.  
  648. /* Binary functions requiring integer argument */
  649.  
  650. #define BINAIRY_INT_FUNCTION(name, plop, op) \
  651.   static int \
  652.   name(Number n1, Number n2, Number r) \
  653.   { if ( !toIntegerNumber(n1) ) \
  654.       return PL_error(plop, 2, NULL, ERR_AR_TYPE, ATOM_integer, n1); \
  655.     if ( !toIntegerNumber(n2) ) \
  656.       return PL_error(plop, 2, NULL, ERR_AR_TYPE, ATOM_integer, n2); \
  657.     r->value.i = n1->value.i op n2->value.i; \
  658.     r->type = V_INTEGER; \
  659.     succeed; \
  660.   }
  661.  
  662. #define BINAIRY_FLOAT_FUNCTION(name, func) \
  663.   static int \
  664.   name(Number n1, Number n2, Number r) \
  665.   { promoteToRealNumber(n1); \
  666.     promoteToRealNumber(n2); \
  667.     r->value.f = func(n1->value.f, n2->value.f); \
  668.     r->type = V_REAL; \
  669.     succeed; \
  670.   }
  671.  
  672. UNAIRY_FLOAT_FUNCTION(ar_sin, sin)
  673. UNAIRY_FLOAT_FUNCTION(ar_cos, cos)
  674. UNAIRY_FLOAT_FUNCTION(ar_tan, tan)
  675. UNAIRY_FLOAT_FUNCTION(ar_atan, atan)
  676. UNAIRY_FLOAT_FUNCTION(ar_exp, exp)
  677.  
  678. BINAIRY_FLOAT_FUNCTION(ar_atan2, atan2)
  679. BINAIRY_FLOAT_FUNCTION(ar_pow, pow)
  680.  
  681. BINAIRY_INT_FUNCTION(ar_mod, "mod", %)
  682. BINAIRY_INT_FUNCTION(ar_disjunct, "\\/", |)
  683. BINAIRY_INT_FUNCTION(ar_conjunct, "/\\", &)
  684. BINAIRY_INT_FUNCTION(ar_shift_right, ">>", >>)
  685. BINAIRY_INT_FUNCTION(ar_shift_left, "<<", <<)
  686. BINAIRY_INT_FUNCTION(ar_xor, "xor", ^)
  687.  
  688. static int
  689. ar_sqrt(Number n1, Number r)
  690. { promoteToRealNumber(n1);
  691.   if ( n1->value.f < 0 )
  692.     return PL_error("sqrt", 1, NULL, ERR_AR_UNDEF);
  693.   r->value.f = sqrt(n1->value.f);
  694.   r->type    = V_REAL;
  695.   succeed;
  696. }
  697.  
  698.  
  699. static int
  700. ar_asin(Number n1, Number r)
  701. { promoteToRealNumber(n1);
  702.   if ( n1->value.f < -1.0 || n1->value.f > 1.0 )
  703.     return PL_error("asin", 1, NULL, ERR_AR_UNDEF);
  704.   r->value.f = asin(n1->value.f);
  705.   r->type    = V_REAL;
  706.   succeed;
  707. }
  708.  
  709.  
  710. static int
  711. ar_acos(Number n1, Number r)
  712. { promoteToRealNumber(n1);
  713.   if ( n1->value.f < -1.0 || n1->value.f > 1.0 )
  714.     return PL_error("acos", 1, NULL, ERR_AR_UNDEF);
  715.   r->value.f = acos(n1->value.f);
  716.   r->type    = V_REAL;
  717.   succeed;
  718. }
  719.  
  720.  
  721. static int
  722. ar_log(Number n1, Number r)
  723. { promoteToRealNumber(n1);
  724.   if ( n1->value.f <= 0.0 )
  725.     return PL_error("log", 1, NULL, ERR_AR_UNDEF);
  726.   r->value.f = log(n1->value.f);
  727.   r->type    = V_REAL;
  728.   succeed;
  729. }
  730.  
  731.  
  732. static int
  733. ar_log10(Number n1, Number r)
  734. { promoteToRealNumber(n1);
  735.   if ( n1->value.f <= 0.0 )
  736.     return PL_error("log10", 1, NULL, ERR_AR_UNDEF);
  737.   r->value.f = log10(n1->value.f);
  738.   r->type    = V_REAL;
  739.   succeed;
  740. }
  741.  
  742.  
  743. static int
  744. ar_div(Number n1, Number n2, Number r)
  745. { if ( !toIntegerNumber(n1) )
  746.     return PL_error("//", 2, NULL, ERR_AR_TYPE, ATOM_integer, n1);
  747.   if ( !toIntegerNumber(n2) )
  748.     return PL_error("//", 2, NULL, ERR_AR_TYPE, ATOM_integer, n2);
  749.   if ( n2->value.i == 0 )
  750.     return PL_error("//", 2, NULL, ERR_DIV_BY_ZERO);
  751.  
  752.   r->value.i = n1->value.i / n2->value.i;
  753.   r->type = V_INTEGER;
  754.  
  755.   succeed;
  756. }
  757.  
  758. static int
  759. ar_sign(Number n1, Number r)
  760. { if ( intNumber(n1) )
  761.     r->value.i = (n1->value.i <   0 ? -1 : n1->value.i >   0 ? 1 : 0);
  762.   else
  763.     r->value.i = (n1->value.f < 0.0 ? -1 : n1->value.f > 0.0 ? 1 : 0);
  764.  
  765.   r->type = V_INTEGER;
  766.   succeed;
  767. }
  768.  
  769.  
  770. static int
  771. ar_rem(Number n1, Number n2, Number r)
  772. { real f;
  773.  
  774.   if ( !toIntegerNumber(n1) )
  775.     return PL_error("rem", 2, NULL, ERR_AR_TYPE, ATOM_integer, n1);
  776.   if ( !toIntegerNumber(n2) )
  777.     return PL_error("rem", 2, NULL, ERR_AR_TYPE, ATOM_integer, n2);
  778.  
  779.   f = (real)n1->value.i / (real)n2->value.i;
  780.   r->value.f = f - (real)((long) f);
  781.   r->type = V_REAL;
  782.   succeed;
  783. }
  784.  
  785.  
  786. static int
  787. ar_divide(Number n1, Number n2, Number r)
  788. { if ( intNumber(n1) && intNumber(n2) )
  789.   { if ( n2->value.i == 0 )
  790.       return PL_error("/", 2, NULL, ERR_DIV_BY_ZERO);
  791.  
  792.     if ( n1->value.i % n2->value.i == 0)
  793.     { r->value.i = n1->value.i / n2->value.i;
  794.       r->type = V_INTEGER;
  795.       succeed;
  796.     }
  797.   }
  798.  
  799.   promoteToRealNumber(n1);
  800.   promoteToRealNumber(n2);
  801.   if ( n2->value.f == 0.0 )
  802.       return PL_error("/", 2, NULL, ERR_DIV_BY_ZERO);
  803.  
  804.   r->value.f = n1->value.f / n2->value.f;
  805.   r->type = V_REAL;
  806.   succeed;
  807. }
  808.  
  809.  
  810. static int
  811. ar_times(Number n1, Number n2, Number r)
  812. { if ( intNumber(n1) && intNumber(n2) )
  813.   { if ( abs(n1->value.i) >= (1 << 15) || abs(n2->value.i) >= (1 << 15) )
  814.     { r->value.f = (real)n1->value.i * (real)n2->value.i;
  815.       r->type = V_REAL;
  816.       succeed;
  817.     }
  818.     r->value.i = n1->value.i * n2->value.i;
  819.     r->type = V_INTEGER;
  820.     succeed;
  821.   }
  822.   
  823.   promoteToRealNumber(n1);
  824.   promoteToRealNumber(n2);
  825.  
  826.   r->value.f = n1->value.f * n2->value.f;
  827.   r->type = V_REAL;
  828.   succeed;
  829. }
  830.  
  831.  
  832. static int
  833. ar_max(Number n1, Number n2, Number r)
  834. { if ( intNumber(n1) && intNumber(n2) )
  835.   { r->value.i = (n1->value.i > n2->value.i ? n1->value.i : n2->value.i);
  836.     r->type = V_INTEGER;
  837.     succeed;
  838.   }
  839.  
  840.   promoteToRealNumber(n1);
  841.   promoteToRealNumber(n2);
  842.  
  843.   r->value.f = (n1->value.f > n2->value.f ? n1->value.f : n2->value.f);
  844.   r->type = V_REAL;
  845.   succeed;
  846. }
  847.  
  848.  
  849. static int
  850. ar_min(Number n1, Number n2, Number r)
  851. { if ( intNumber(n1) && intNumber(n2) )
  852.   { r->value.i = (n1->value.i < n2->value.i ? n1->value.i : n2->value.i);
  853.     r->type = V_INTEGER;
  854.     succeed;
  855.   }
  856.  
  857.   promoteToRealNumber(n1);
  858.   promoteToRealNumber(n2);
  859.  
  860.   r->value.f = (n1->value.f < n2->value.f ? n1->value.f : n2->value.f);
  861.   r->type = V_REAL;
  862.   succeed;
  863. }
  864.  
  865.  
  866. static int
  867. ar_negation(Number n1, Number r)
  868. { if ( !toIntegerNumber(n1) )
  869.     return PL_error("\\", 1, NULL, ERR_AR_TYPE, ATOM_integer, n1);
  870.  
  871.   r->value.i = ~n1->value.i;
  872.   r->type = V_INTEGER;
  873.   succeed;
  874. }
  875.  
  876.  
  877. static int
  878. ar_u_minus(Number n1, Number r)
  879. { if ( intNumber(n1) )
  880.   { r->value.i = -n1->value.i;
  881.     r->type = V_INTEGER;
  882.   } else
  883.   { r->value.f = -n1->value.f;
  884.     r->type = V_REAL;
  885.   }
  886.  
  887.   succeed;
  888. }
  889.  
  890.  
  891. #undef abs
  892. #define abs(a) ((a) < 0 ? -(a) : (a))
  893.  
  894. static int
  895. ar_abs(Number n1, Number r)
  896. { if ( intNumber(n1) )
  897.   { r->value.i = abs(n1->value.i);
  898.     r->type = V_INTEGER;
  899.   } else
  900.   { r->value.f = abs(n1->value.f);
  901.     r->type = V_REAL;
  902.   }
  903.  
  904.   succeed;
  905. }
  906.  
  907.  
  908. static int
  909. ar_integer(Number n1, Number r)
  910. { if ( intNumber(n1) )
  911.   { *r = *n1;
  912.     succeed;
  913.   } else
  914.   { if ( n1->value.f < PLMAXINT && n1->value.f > PLMININT )
  915.     { r->value.i = (n1->value.f > 0 ? (long)(n1->value.f + 0.5)
  916.                         : (long)(n1->value.f - 0.5));
  917.       r->type = V_INTEGER;
  918.       succeed;
  919.     }
  920. #ifdef HAVE_RINT
  921.     r->value.f = rint(n1->value.f);
  922.     r->type = V_REAL;
  923.     succeed;
  924. #else
  925.     return PL_error("integer", 1, NULL, ERR_EVALUATION, ATOM_int_overflow);
  926. #endif
  927.   }
  928. }
  929.  
  930.  
  931. static int
  932. ar_float(Number n1, Number r)
  933. { *r = *n1;
  934.   promoteToRealNumber(r);
  935.   r->type = V_EXPLICIT_REAL;        /* avoid canoniseNumber() */
  936.  
  937.   succeed;
  938. }
  939.  
  940.  
  941. static int
  942. ar_floor(Number n1, Number r)
  943. { if ( intNumber(n1) )
  944.     *r = *n1;
  945.   else
  946.   {
  947. #ifdef HAVE_FLOOR
  948.     r->value.f = floor(n1->value.f);
  949.     r->type = V_REAL;
  950. #else
  951.     r->value.i = (long)n1->value.f;
  952.     if ( n1->value.f < 0 && (real)r->value.i != n1->value.f )
  953.       r->value.i--;
  954.     r->type = V_INTEGER;
  955. #endif
  956.   }
  957.   succeed;
  958. }
  959.  
  960.  
  961. static int
  962. ar_ceil(Number n1, Number r)
  963. { if ( intNumber(n1) )
  964.     *r = *n1;
  965.   else
  966.   {
  967. #ifdef HAVE_CEIL
  968.     r->value.f = ceil(n1->value.f);
  969.     r->type = V_REAL;
  970. #else
  971.     r->value.i = (long)n1->value.f;
  972.     if ( (real)r->value.i < n1->value.f )
  973.        r->value.i++;
  974.     r->type = V_INTEGER;
  975. #endif
  976.   }
  977.  
  978.   succeed;
  979. }
  980.  
  981.  
  982. static int
  983. ar_float_fractional_part(Number n1, Number r)
  984. { if ( intNumber(n1) )
  985.   { r->value.i = 0;
  986.     r->type = V_INTEGER;
  987.   } else
  988.   { if ( n1->value.f > 0 )
  989.     { r->value.f = n1->value.f - floor(n1->value.f);
  990.     } else
  991.     { TRY(ar_ceil(n1, r));
  992.       r->value.f = n1->value.f - ceil(n1->value.f);
  993.     }
  994.     r->type = V_REAL;
  995.   }
  996.  
  997.   succeed;
  998. }
  999.  
  1000.  
  1001. static int
  1002. ar_float_integer_part(Number n1, Number r)
  1003. { if ( intNumber(n1) )
  1004.     *r = *n1;
  1005.   else
  1006.   { if ( n1->value.f > 0 )
  1007.       return ar_floor(n1, r);
  1008.     else
  1009.       return ar_ceil(n1, r);
  1010.   }
  1011.  
  1012.   succeed;
  1013. }
  1014.  
  1015.  
  1016. static int
  1017. ar_truncate(Number n1, Number r)
  1018. { return ar_float_integer_part(n1, r);
  1019. }
  1020.  
  1021.  
  1022. static int
  1023. ar_random(Number n1, Number r)
  1024. { if ( !toIntegerNumber(n1) )
  1025.     return PL_error("random", 1, NULL, ERR_AR_TYPE, ATOM_integer, n1);
  1026.  
  1027.   r->value.i = Random() % n1->value.i;
  1028.   r->type = V_INTEGER;
  1029.  
  1030.   succeed;
  1031. }
  1032.  
  1033.  
  1034. static int
  1035. ar_pi(Number r)
  1036. { r->value.f = M_PI;
  1037.  
  1038.   r->type = V_REAL;
  1039.   succeed;
  1040. }
  1041.  
  1042.  
  1043. static int
  1044. ar_e(Number r)
  1045. { r->value.f = M_E;
  1046.  
  1047.   r->type = V_REAL;
  1048.   succeed;
  1049. }
  1050.  
  1051.  
  1052. static int
  1053. ar_cputime(Number r)
  1054. { r->value.f = CpuTime();
  1055.  
  1056.   r->type = V_REAL;
  1057.   succeed;
  1058. }
  1059.  
  1060.  
  1061.         /********************************
  1062.         *       PROLOG CONNECTION       *
  1063.         *********************************/
  1064.  
  1065. word
  1066. pl_is(term_t v, term_t e)
  1067. { number arg;
  1068.  
  1069.   if ( valueExpression(e, &arg) )
  1070.   { canoniseNumber(&arg);
  1071.     return _PL_unify_number(v, &arg);
  1072.   }
  1073.  
  1074.   fail;
  1075. }
  1076.  
  1077.  
  1078. #if O_PROLOG_FUNCTIONS
  1079. word
  1080. pl_arithmetic_function(term_t descr)
  1081. { Procedure proc;
  1082.   Definition def;
  1083.   functor_t fd;
  1084.   FunctorDef fdef;
  1085.   ArithFunction f;
  1086.   Module m = NULL;
  1087.   term_t head = PL_new_term_ref();
  1088.   int v;
  1089.  
  1090.   PL_strip_module(descr, &m, head);
  1091.   if ( !PL_get_functor(head, &fd) )
  1092.     return warning("arithmetic_function/1: Illegal head");
  1093.   fdef = valueFunctor(fd);
  1094.   if ( fdef->arity < 1 )
  1095.     return warning("arithmetic_function/1: Illegal arity");
  1096.  
  1097.   proc = lookupProcedure(fd, m);
  1098.   def = proc->definition;
  1099.   fd = lookupFunctorDef(fdef->name, fdef->arity - 1);
  1100.   if ( (f = isCurrentArithFunction(fd, m)) && f->module == m )
  1101.     succeed;                /* already registered */
  1102.  
  1103.   v = functorHashValue(fd, ARITHHASHSIZE);
  1104.   f = allocHeap(sizeof(struct arithFunction));
  1105.   f->functor  = fd;
  1106.   f->function = NULL;
  1107.   f->module   = m;
  1108.   f->proc     = proc;
  1109.  
  1110.   startCritical;
  1111.   f->next     = arithFunctionTable[v];
  1112.   arithFunctionTable[v] = f;  
  1113.   registerFunction(f);
  1114.   endCritical;
  1115.  
  1116.   succeed;
  1117. }
  1118.  
  1119. word
  1120. pl_current_arithmetic_function(term_t f, word h)
  1121. { ArithFunction a;
  1122.   Module m = NULL;
  1123.   term_t head = PL_new_term_ref();
  1124.  
  1125.   switch( ForeignControl(h) )
  1126.   { case FRG_FIRST_CALL:
  1127.     { functor_t fd;
  1128.  
  1129.       PL_strip_module(f, &m, head);
  1130.  
  1131.       if ( PL_is_variable(head) )
  1132.       { a = arithFunctionTable[0];
  1133.         break;
  1134.       } else if ( PL_get_functor(head, &fd) )
  1135.       {    return isCurrentArithFunction(fd, m) ? TRUE : FALSE;
  1136.       } else
  1137.         return warning("current_arithmetic_function/2: instantiation fault");
  1138.     }
  1139.     case FRG_REDO:
  1140.       PL_strip_module(f, &m, head);
  1141.  
  1142.       a = ForeignContextPtr(h);
  1143.       break;
  1144.     case FRG_CUTTED:
  1145.     default:
  1146.       succeed;
  1147.   }
  1148.  
  1149.   for( ; a; a = a->next )
  1150.   { Module m2;
  1151.  
  1152.     while( isTableRef(a) )
  1153.     { a = unTableRef(ArithFunction, a);
  1154.       if ( !a )
  1155.         fail;
  1156.     }
  1157.  
  1158.     for(m2 = m; m2; m2 = m2->super)
  1159.     { if ( m2 == a->module && a == isCurrentArithFunction(a->functor, m) )
  1160.       { if ( PL_unify_functor(f, a->functor) )
  1161.       return_next_table(ArithFunction, a, ;);
  1162.       }
  1163.     }
  1164.   }
  1165.  
  1166.   fail;
  1167. }
  1168.  
  1169. #endif /* O_PROLOG_FUNCTIONS */
  1170.  
  1171. typedef struct
  1172. { functor_t    functor;
  1173.   ArithF    function;
  1174. } ar_funcdef;
  1175.  
  1176. #define ADD(functor, func) { functor, func }
  1177.  
  1178. static const ar_funcdef ar_funcdefs[] = {
  1179.   ADD(FUNCTOR_plus2,        ar_add),
  1180.   ADD(FUNCTOR_minus2,        ar_minus),
  1181.   ADD(FUNCTOR_star2,        ar_times),
  1182.   ADD(FUNCTOR_divide2,        ar_divide),
  1183.   ADD(FUNCTOR_minus1,        ar_u_minus),
  1184.   ADD(FUNCTOR_abs1,        ar_abs),
  1185.   ADD(FUNCTOR_max2,        ar_max),
  1186.   ADD(FUNCTOR_min2,        ar_min),
  1187.  
  1188.   ADD(FUNCTOR_mod2,        ar_mod),
  1189.   ADD(FUNCTOR_rem2,        ar_rem),
  1190.   ADD(FUNCTOR_div2,        ar_div),
  1191.   ADD(FUNCTOR_sign1,        ar_sign),
  1192.  
  1193.   ADD(FUNCTOR_and2,        ar_conjunct),
  1194.   ADD(FUNCTOR_or2,        ar_disjunct),
  1195.   ADD(FUNCTOR_rshift2,        ar_shift_right),
  1196.   ADD(FUNCTOR_lshift2,        ar_shift_left),
  1197.   ADD(FUNCTOR_xor2,        ar_xor),
  1198.   ADD(FUNCTOR_backslash1,    ar_negation),
  1199.  
  1200.   ADD(FUNCTOR_random1,        ar_random),
  1201.  
  1202.   ADD(FUNCTOR_integer1,        ar_integer),
  1203.   ADD(FUNCTOR_round1,        ar_integer),
  1204.   ADD(FUNCTOR_truncate1,    ar_truncate),
  1205.   ADD(FUNCTOR_float1,        ar_float),
  1206.   ADD(FUNCTOR_floor1,        ar_floor),
  1207.   ADD(FUNCTOR_ceil1,        ar_ceil),
  1208.   ADD(FUNCTOR_ceiling1,        ar_ceil),
  1209.   ADD(FUNCTOR_float_fractional_part1, ar_float_fractional_part),
  1210.   ADD(FUNCTOR_float_integer_part1, ar_float_integer_part),
  1211.  
  1212.   ADD(FUNCTOR_sqrt1,        ar_sqrt),
  1213.   ADD(FUNCTOR_sin1,        ar_sin),
  1214.   ADD(FUNCTOR_cos1,        ar_cos),
  1215.   ADD(FUNCTOR_tan1,        ar_tan),
  1216.   ADD(FUNCTOR_asin1,        ar_asin),
  1217.   ADD(FUNCTOR_acos1,        ar_acos),
  1218.   ADD(FUNCTOR_atan1,        ar_atan),
  1219.   ADD(FUNCTOR_atan2,        ar_atan2),
  1220.   ADD(FUNCTOR_log1,        ar_log),
  1221.   ADD(FUNCTOR_exp1,        ar_exp),
  1222.   ADD(FUNCTOR_log101,        ar_log10),
  1223.   ADD(FUNCTOR_hat2,        ar_pow),
  1224.   ADD(FUNCTOR_doublestar2,    ar_pow),
  1225.   ADD(FUNCTOR_pi0,        ar_pi),
  1226.   ADD(FUNCTOR_e0,        ar_e),
  1227.  
  1228.   ADD(FUNCTOR_cputime0,        ar_cputime),
  1229. };
  1230.  
  1231. #undef ADD
  1232.  
  1233. static void
  1234. registerFunction(ArithFunction f)
  1235. { f->index = entriesBuffer(function_array, ArithFunction);
  1236.   addBuffer(function_array, f, ArithFunction);
  1237. }
  1238.  
  1239.  
  1240. static void
  1241. registerBuiltinFunctions()
  1242. { int n, size = sizeof(ar_funcdefs)/sizeof(ar_funcdef);
  1243.   ArithFunction f = allocHeap(size * sizeof(struct arithFunction));
  1244.   const ar_funcdef *d;
  1245.  
  1246.                     /* grow to desired size immediately */
  1247.   growBuffer(function_array, size * sizeof(ArithFunction));
  1248.   memset(f, 0, size * sizeof(struct arithFunction));
  1249.  
  1250.   for(d = ar_funcdefs, n=0; n<size; n++, f++, d++)
  1251.   { int v = functorHashValue(d->functor, ARITHHASHSIZE);
  1252.  
  1253.     f->functor  = d->functor;
  1254.     f->function = d->function;
  1255.     f->module   = MODULE_system;
  1256.     f->next     = arithFunctionTable[v];
  1257.     arithFunctionTable[v] = f;
  1258.     registerFunction(f);
  1259.     DEBUG(1, Sdprintf("Registered %s/%d at %d, index=%d\n",
  1260.               stringAtom(nameFunctor(f->functor)),
  1261.               arityFunctor(f->functor),
  1262.               v,
  1263.               f->index));
  1264.   }                   
  1265. }
  1266.  
  1267.  
  1268. void
  1269. initArith(void)
  1270. #ifdef SIGFPE
  1271.   pl_signal(SIGFPE, (handler_t) realExceptionHandler);
  1272. #endif
  1273. #if __TURBOC__
  1274.   setmatherr(realExceptionHandler);
  1275. #endif
  1276.  
  1277.   initBuffer(function_array);
  1278.                     /* link the table to enumerate */
  1279.   { ArithFunction *f;
  1280.     int n;
  1281.  
  1282.     for(n=0, f = arithFunctionTable; n < (ARITHHASHSIZE-1); n++, f++)
  1283.       *f = makeTableRef(f+1);
  1284.   }
  1285.  
  1286.   registerBuiltinFunctions();
  1287. }
  1288.  
  1289. #if O_COMPILE_ARITH
  1290.  
  1291.         /********************************
  1292.         *    VIRTUAL MACHINE SUPPORT    *
  1293.         *********************************/
  1294.  
  1295. int
  1296. indexArithFunction(functor_t fdef, register Module m)
  1297. { ArithFunction f;
  1298.  
  1299.   if ( !(f = isCurrentArithFunction(fdef, m)) )
  1300.     return -1;
  1301.  
  1302.   return (int)f->index;
  1303. }
  1304.  
  1305.  
  1306. functor_t
  1307. functorArithFunction(int n)
  1308. { return FunctionFromIndex(n)->functor;
  1309. }
  1310.  
  1311.  
  1312. bool
  1313. ar_func_n(code n, int argc, Number *stack)
  1314. { number result;
  1315.   int rval;
  1316.   ArithFunction f = FunctionFromIndex((int)n);
  1317.   Number sp = *stack;
  1318.  
  1319.   sp -= argc;
  1320.   if ( f->proc )
  1321.   { LocalFrame lSave = lTop;        /* TBD (check with stack!) */
  1322.     term_t h0;
  1323.     int n;
  1324.  
  1325.     lTop = (LocalFrame) (*stack);
  1326.     h0   = PL_new_term_refs(argc+1);
  1327.     
  1328.     for(n=0; n<argc; n++)
  1329.       _PL_put_number(h0+n, &sp[n]);
  1330.  
  1331.     rval = prologFunction(f, h0, &result);
  1332.     lTop = lSave;
  1333.   } else
  1334.   { switch(argc)
  1335.     { case 0:
  1336.     rval = (*f->function)(&result);
  1337.         break;
  1338.       case 1:
  1339.     rval = (*f->function)(sp, &result);
  1340.         break;
  1341.       case 2:
  1342.     rval = (*f->function)(sp, &sp[1], &result);
  1343.         break;
  1344.       default:
  1345.     rval = FALSE;
  1346.         sysError("Too many arguments to arithmetic function");
  1347.     }
  1348.   }
  1349.  
  1350.   if ( rval )
  1351.   { if ( result.type == V_REAL )
  1352.     {
  1353. #ifdef HUGE_VAL
  1354.       if ( result.value.f == HUGE_VAL )
  1355.     return PL_error(NULL, 0, NULL, ERR_AR_OVERFLOW);
  1356. #endif
  1357. #ifdef HAVE_ISNAN
  1358.       if ( isnan(result.value.f) )
  1359.     return PL_error(NULL, 0, NULL, ERR_AR_UNDEF);
  1360. #endif
  1361.     }
  1362.  
  1363.     *sp++ = result;
  1364.     *stack = sp;
  1365.   }
  1366.  
  1367.   return rval;
  1368. }
  1369.  
  1370. #endif /* O_COMPILE_ARITH */
  1371.